package com.personal.gateway.filter;

import com.personal.gateway.constant.LoginUserInfoConstant;
import com.personal.gateway.entity.FlinkGatewayRoute;
import com.personal.gateway.mapper.FlinkGatewayRouteMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.net.URI;
import java.util.List;
import java.util.stream.Collectors;

import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR;

@Slf4j
@Component
public class GatewayFlinkFilter implements GlobalFilter, Ordered {

    @Resource
    private FlinkGatewayRouteMapper flinkGatewayRouteMapper;

    @Resource
    private LoginUserInfoConstant loginUserInfoConstant;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();

        if (null == request.getCookies().get("token")){
            String redirectUrl = "http://localhost:8569";
            response.getHeaders().set(HttpHeaders.LOCATION, redirectUrl);
            response.setStatusCode(HttpStatus.SEE_OTHER);
            response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");
            return response.setComplete();
        }
        String token = request.getCookies().get("token").get(0).getValue();
        String userName = loginUserInfoConstant.getUserByToken(token);
        if (StringUtils.isBlank(userName)) {
            String redirectUrl = "http://localhost:8569";
            response.getHeaders().set(HttpHeaders.LOCATION, redirectUrl);
            response.setStatusCode(HttpStatus.SEE_OTHER);
            response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");
            return response.setComplete();
        }

        String path = request.getPath().toString();
        // log.info("访问地址： {}", path);
        if ("/favicon.ico".equals(path)) {
            return chain.filter(exchange);
        }

        List<FlinkGatewayRoute> routes = flinkGatewayRouteMapper.list();
        if (routes.stream().map(x -> "/" + x.getId()).collect(Collectors.toList()).contains(path)) {
            return chain.filter(exchange);
        }

        if (null == request.getCookies().get("current-flink-name")){
            return chain.filter(exchange);
        }
        String name = request.getCookies().get("current-flink-name").get(0).getValue();
        if (StringUtils.isBlank(name) || name.equals("null")) {
            return chain.filter(exchange);
        }

        String url = routes.stream().filter(x -> x.getRouteId().equals(name)).collect(Collectors.toList()).get(0).getRouteUri();
        URI uri = UriComponentsBuilder.fromHttpUrl(url + path.replace("/" + name, "")).build().toUri();
        Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
        assert route != null;
        Route newRoute = Route.async().asyncPredicate(route.getPredicate())
                .filters(route.getFilters())
                .id(route.getId())
                .order(route.getOrder())
                .uri(uri)
                .build();
        exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, newRoute);
        return chain.filter(exchange.mutate().request(exchange.getRequest().mutate().build()).build());
    }

    @Override
    public int getOrder() {
        return 0;
    }

}
